﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace NougakudoSetupTool
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            SetDefaultEnable();
        }

        string openFolderPath = "";
        Nougakudo.Runtime runtime;
        Dictionary<string, Nougakudo.Application> appsInfo;

        void SetDefaultEnable()
        {
            grpNougakudo.IsEnabled = true;
            grpApplication.IsEnabled = true;
            btnLoadConfig.IsEnabled = false;
            cmbApplications.IsEnabled = false;
        }

        private void radioNew_Checked(object sender, RoutedEventArgs e)
        {
            if (grpNougakudo == null) return;   // default setting for constructor
            SetDefaultEnable();
        }

        private void radioUpdate_Checked(object sender, RoutedEventArgs e)
        {
            grpNougakudo.IsEnabled = false;
            grpApplication.IsEnabled = false;
            btnLoadConfig.IsEnabled = true;
            
        }

        private void btnOpenOutputFolder_Click(object sender, RoutedEventArgs e)
        {
            var dialog = new System.Windows.Forms.FolderBrowserDialog();
            if (openFolderPath == "")
                dialog.SelectedPath = AppDomain.CurrentDomain.BaseDirectory;
            else
                dialog.SelectedPath = openFolderPath;
            dialog.ShowNewFolderButton = false;
            var ret = dialog.ShowDialog();
            if (ret == System.Windows.Forms.DialogResult.OK)
            {
                txtOutputFolder.Text = dialog.SelectedPath;
                openFolderPath = dialog.SelectedPath;
            }

        }

        private void btnLoadConfig_Click(object sender, RoutedEventArgs e)
        {
            var retTuple = Nougakudo.LoadConfiguration(txtOutputFolder.Text);
            if (!retTuple.Item1)
            {
                MessageBox.Show("Error: load configuration: ");
                return;
            }

            runtime = retTuple.Item2;
            appsInfo = retTuple.Item3;

            txtRuntimeVersion.Text = runtime.Version;
            txtRuntimeFolder.Text = "";

            cmbApplications.ItemsSource = null;
            cmbApplications.Items.Clear();
            cmbApplications.ItemsSource = appsInfo.Keys.ToArray();

            SetDefaultEnable();
            cmbApplications.IsEnabled = true;
            btnLoadConfig.IsEnabled = true;
        }

        private void btnOpenRuntimeFolder_Click(object sender, RoutedEventArgs e)
        {
            var dialog = new System.Windows.Forms.FolderBrowserDialog();
            var folder = System.IO.Path.Combine(
                Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
                @"AppData\Roaming");
            dialog.SelectedPath = folder;
            dialog.ShowNewFolderButton = false;
            var ret = dialog.ShowDialog();
            if (ret == System.Windows.Forms.DialogResult.OK)
            {
                txtRuntimeFolder.Text = dialog.SelectedPath;
                openFolderPath = dialog.SelectedPath;
            }

        }

        private void cmbApplications_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (cmbApplications.SelectedValue == null)
            {
                txtAppVersion.Text = "";
                cmbAppEnvironment.SelectedIndex = 0;
                txtAppNumOfProcessors.Text = "";
                txtAppFolder.Text = "";
                chkvHost.IsChecked = false;                         // Add for NougakuDo 1.1.0 above.
            }
            else
            {
                var name = cmbApplications.SelectedValue.ToString();
                txtAppVersion.Text = appsInfo[name].Version;
                cmbAppEnvironment.SelectedIndex = getEnvironmentIndex(appsInfo[name].Environment);
                txtAppNumOfProcessors.Text = appsInfo[name].NumOfProcessors;
                txtAppFolder.Text = name;
                chkvHost.IsChecked = appsInfo[name].VirtualHost;    // Add for NougakuDo 1.1.0 above.
            }
        }

        int getEnvironmentIndex(string environment)
        {
            int index = -1;
            foreach (ComboBoxItem i in cmbAppEnvironment.Items)
            {
                index++;
                if (i.Content.ToString() == environment)
                {
                    return index;
                }
            }

            return -1;
        }

        private void btnOpenAppFolder_Click(object sender, RoutedEventArgs e)
        {
            var dialog = new System.Windows.Forms.FolderBrowserDialog();
            if (openFolderPath == "")
                dialog.SelectedPath = AppDomain.CurrentDomain.BaseDirectory;
            else
                dialog.SelectedPath = openFolderPath;
            dialog.ShowNewFolderButton = false;
            var ret = dialog.ShowDialog();
            if (ret == System.Windows.Forms.DialogResult.OK)
            {
                txtAppFolder.Text = dialog.SelectedPath;
                openFolderPath = dialog.SelectedPath;
            }

        }

        private void btnGenerate_Click(object sender, RoutedEventArgs e)
        {
            var ret = CheckInputData();
            if (!ret) return;
            var d = GetInputData();
            btnGenerate.IsEnabled = false;
            bool createZip = false;
            var ret2 = Nougakudo.SaveConfiguration(txtOutputFolder.Text, d.Item1, d.Item2, (bool) radioUpdate.IsChecked);
            if (!ret2.Item1)
            {
                MessageBox.Show("Error: save confioguration: " + ret2.Item2);
                btnGenerate.IsEnabled = true;
                return;
            }

            if (txtRuntimeFolder.Text != "")
            {
                createZip = true;
                ret2 = Nougakudo.CreateZip(txtRuntimeFolder.Text, txtOutputFolder.Text, true);
            }
            if (!ret2.Item1)
            {
                MessageBox.Show("Error: create zip file for NougakuDo: " + ret2.Item2);
                btnGenerate.IsEnabled = true;
                return;
            }

            if (txtAppFolder.Text.Contains(@"\"))
            {
                createZip = true;
                ret2 = Nougakudo.CreateZip(txtAppFolder.Text, txtOutputFolder.Text);
            }
            if (!ret2.Item1)
            {
                MessageBox.Show("Error: create zip file for Application: " + ret2.Item2);
                btnGenerate.IsEnabled = true;
                return;
            }

            MessageBox.Show("Success! please see the output folder. Wait 20 seconds.");
            if (createZip)
                System.Threading.Thread.Sleep(20000);
            btnGenerate.IsEnabled = true;
            // reload configuration.
            radioUpdate.IsChecked = true;
            btnLoadConfig_Click(sender, e);
            btnLoadConfig.Focus();

        }


        Tuple<Nougakudo.Runtime, Nougakudo.Application> GetInputData()
        {
            Nougakudo.Runtime runtime = new Nougakudo.Runtime() { Version = txtRuntimeVersion.Text };
            Nougakudo.Application appInfo = new Nougakudo.Application()
                                            {
                                                Name = System.IO.Path.GetFileName(txtAppFolder.Text),
                                                Version = txtAppVersion.Text,
                                                Environment = cmbAppEnvironment.SelectionBoxItem.ToString(),
                                                NumOfProcessors = txtAppNumOfProcessors.Text,
                                                VirtualHost = (bool)chkvHost.IsChecked       // Add for NougakuDo 1.1.0 above.
                                            };
            return new Tuple<Nougakudo.Runtime, Nougakudo.Application>(runtime, appInfo);
        }

        bool CheckInputData()
        {
            List<string> messages = new List<string>();
            if (!System.IO.Directory.Exists(txtOutputFolder.Text))
                messages.Add("OutPutFolder: " + txtOutputFolder.Text + " not exists.");
            if (txtRuntimeVersion.Text == "")
                messages.Add("Runtime Version must need.");
            if (txtRuntimeFolder.Text != "")
            {
                if (!System.IO.Directory.Exists(txtRuntimeFolder.Text))
                    messages.Add("Runtime Folder: " + txtRuntimeFolder.Text + " not exists.");
            }

            if (txtAppVersion.Text == "")
                messages.Add("Application Version must need.");

            if (txtAppNumOfProcessors.Text == "")
                messages.Add("Application # of processors must need.");
            if (txtAppFolder.Text == "")
                messages.Add("Application folder must need.");
            else if (txtAppFolder.Text.Contains(@"\") &&
                    !System.IO.Directory.Exists(txtAppFolder.Text))
                messages.Add("Application Folder: " + txtAppFolder.Text + " not exists.");
            else if (txtAppFolder.Text.Contains(@"\") &&
                    !System.IO.File.Exists(System.IO.Path.Combine(txtAppFolder.Text, "config.ru")))
                messages.Add("Application Folder: config.ru not exists.");

            else if (System.IO.Path.GetFileName(txtAppFolder.Text) == "")
                messages.Add("Application folder don't be root.");


            if (messages.Count != 0)
            {
                string msg = GetMessage(messages);
                MessageBox.Show("Input errors : " + msg, "Input error");
                return false;
            }

            if (txtRuntimeFolder.Text == "")
                messages.Add("Runtime : configuration update only?");
            if (!txtAppFolder.Text.Contains(@"\"))
                messages.Add("Application : configuration update only?");
            if (messages.Count != 0)
            {
                string msg = GetMessage(messages);
                var ret = MessageBox.Show("Confirm : " + msg, "Confirm", MessageBoxButton.OKCancel);
                if (ret == MessageBoxResult.Cancel)
                    return false;
            }
            return true;
        }

        string GetMessage(List<string> messages)
        {
            string msg = "";
            foreach (var m in messages)
            {
                msg += "\r\n" + m;
            }
            return msg;
        }

        // Add for NougakuDo 1.1.0 above.
        private void chkvHost_GotFocus(object sender, RoutedEventArgs e)
        {
            StackPanel p = (StackPanel)chkvHost.ToolTip;
            string msg = "";
            foreach (var t in p.Children)
            {
                msg += ((TextBlock)t).Text + " ";
            }
            statusBar1.Items.Add(msg);
        }

        // Add for NougakuDo 1.1.0 above.
        private void chkvHost_LostFocus(object sender, RoutedEventArgs e)
        {
            statusBar1.Items.Clear();
        }
    }
}
